package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.LongTermsBucket;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.PinYinUtils;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.search.repository.AlbumIndexRepository;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private SuggestIndexRepository suggestIndexRepository;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private AlbumIndexRepository albumIndexRepository;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Override
    public void upperAlbum(Long albumId) {
        //  给数据载体赋值：
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();

        //  多线程：
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //  远程调用方法
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            //  判断当前这个返回结果集是否为空
            Assert.notNull(albumInfoResult, "专辑信息结果集不存在");
            AlbumInfo albumInfo = albumInfoResult.getData();
            //  实现属性赋值：
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            return albumInfo;
        }, threadPoolExecutor);


        //  获取三级分类数据
        CompletableFuture cateCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //  获取三级分类Id
            Long category3Id = albumInfo.getCategory3Id();
            Result<BaseCategoryView> categoryViewResult = categoryFeignClient.getCategoryView(category3Id);
            Assert.notNull(categoryViewResult, "分类数据结果集不存在");
            BaseCategoryView baseCategoryView = categoryViewResult.getData();
            Assert.notNull(baseCategoryView, "分类数据不存在");
            albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
        }, threadPoolExecutor);


        //  获取主播信息
        CompletableFuture userCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(albumInfo.getUserId());
            //  判断
            Assert.notNull(userInfoVoResult, "主播信息结果集不存在");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "主播信息不存在");
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        }, threadPoolExecutor);


        //  赋值属性与属性值！
        //  本质需要赋值 属性Id 与属性值Id;
        //  一个专辑对应的属性与属性值有多少个? List
        //  远程调用获取数据
        CompletableFuture<Void> attrCompletableFuture = CompletableFuture.runAsync(() -> {
            Result<List<AlbumAttributeValue>> listResult = albumInfoFeignClient.findAlbumAttributeValue(albumId);
            //  判断
            Assert.notNull(listResult, "属性值结果集不存在");
            List<AlbumAttributeValue> albumAttributeValueList = listResult.getData();
            Assert.notNull(albumAttributeValueList, "属性不存在");
            //  返回的是一个集合，循环遍历获取数据并赋值！
            List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueList.stream().map(albumAttributeValue -> {
                //  创建对象
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                //  返回数据
                return attributeValueIndex;
            }).collect(Collectors.toList());
            //  赋值完成
            albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
        }, threadPoolExecutor);
        //  可以初始化赋值： 一种查询数据库: album_stat; 根据专辑Id;
        Integer playStatNum = new Random().nextInt(100000);
        Integer subscribeStatNum = new Random().nextInt(10000000);
        Integer buyStatNum = new Random().nextInt(10000);
        Integer commentStatNum = new Random().nextInt(100000);
        Double hotScore = new Random().nextDouble(1000000);
        albumInfoIndex.setPlayStatNum(playStatNum);
        albumInfoIndex.setSubscribeStatNum(subscribeStatNum);
        albumInfoIndex.setBuyStatNum(buyStatNum);
        albumInfoIndex.setCommentStatNum(commentStatNum);
        albumInfoIndex.setHotScore(hotScore);

        //  多任务组合：
        CompletableFuture.allOf(albumInfoCompletableFuture, cateCompletableFuture, userCompletableFuture, attrCompletableFuture).join();

        //  实现上架
        albumIndexRepository.save(albumInfoIndex);

        //  给提词类赋值： title:三国;  sanguo;  sg;
        SuggestIndex suggestIndex = new SuggestIndex();
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumTitle())}));
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumTitle())}));
        suggestIndexRepository.save(suggestIndex);

        //  简介
        SuggestIndex suggestIndexInfo = new SuggestIndex();
        suggestIndexInfo.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndexInfo.setTitle(albumInfoIndex.getAlbumIntro());
        suggestIndexInfo.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        suggestIndexInfo.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumIntro())}));
        suggestIndexInfo.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumIntro())}));
        suggestIndexRepository.save(suggestIndexInfo);


        //  将专辑Id添加到布隆过滤器
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        bloomFilter.add(albumId);
        //  redisTemplate.opsForValue().setBit("",albumId,true);

    }

    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String ranking) {
        //  hget key field;
        return (List<AlbumInfoIndex>) this.redisTemplate.opsForHash().get(RedisConstant.RANKING_KEY_PREFIX+category1Id, ranking);
    }

    @Override
    public void updateLatelyAlbumRanking() {
        //  先查询到所有的一级分类Id
        Result<List<BaseCategory1>> baseCategory1Result =categoryFeignClient.findCategory1IdList();
        Assert.notNull(baseCategory1Result, "一级分类数据不存在");
        List<BaseCategory1> baseCategory1List = baseCategory1Result.getData();
        Assert.notNull(baseCategory1List, "一级分类数据不存在");
        //  循环遍历；
        for (BaseCategory1 baseCategory1 : baseCategory1List) {
            //  每一级分类Id 都需要有5个维度；
            String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            for (String rankingDimension : rankingDimensionArray) {
                //  根据一级分类Id，维度，查询数据，并排序
                //  调用es客户端对象执行dsl语句;
                SearchResponse<AlbumInfoIndex> searchResponse = null;
                try {
                    searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                                    .query(q -> q.match(m -> m.field("category1Id").query(baseCategory1.getId())))
                                    .sort(st -> st.field(f -> f.field(rankingDimension).order(SortOrder.Desc)))
                            ,
                            AlbumInfoIndex.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

                //  利用查询结果集中的数据，放入redis中！
                List<AlbumInfoIndex> albumInfoIndexList = searchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
                //  hset key field value; key=category1Id; field=commentStatNum value=List<AlbumInfo>
                this.redisTemplate.opsForHash().put(RedisConstant.RANKING_KEY_PREFIX+baseCategory1.getId(),rankingDimension,albumInfoIndexList);
            }
        }
    }

    @Override
    public List<Map<String, Object>> getChannelAlbumInfo(Long category1Id) {
        //  创建Map集合
        //  List<Map<String, Object>> list = new ArrayList<>();
        //  根据一级分类Id找到三级分类对象集合;
        Result<List<BaseCategory3>> baseCategory3ListResult = categoryFeignClient.findTopBaseCategory3(category1Id);
        Assert.notNull(baseCategory3ListResult, "三级分类数据不存在");
        List<BaseCategory3> baseCategory3List = baseCategory3ListResult.getData();
        //  key=category3Id     value=BaseCategory3
        Map<Long, BaseCategory3> category3Map = baseCategory3List.stream().collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));

        //  判断
        Assert.notNull(baseCategory3List, "三级分类数据不存在");
        //  先获取到三级分类 Id 集合
        //        List<Long> category3IdList = baseCategory3List.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        //        //  category3IdList 专辑为 List<FieldValue> 形式！
        //        List<FieldValue> fieldValueList = category3IdList.stream().map(id -> FieldValue.of(id)).collect(Collectors.toList());
        //        List<FieldValue> valueList = baseCategory3List.stream().map(baseCategory3 -> {
        //            return FieldValue.of(baseCategory3.getId());
        //        }).collect(Collectors.toList());
        //  获取到三级分类Id集合
        List<FieldValue> fieldValueList = baseCategory3List.stream().map(baseCategory3 -> FieldValue.of(baseCategory3.getId())).collect(Collectors.toList());

        //  根据三级分类Id 查询 转集合.
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                            .query(q -> q.terms(t -> t.field("category3Id").terms(t1 -> t1.value(fieldValueList))))
                            .aggregations("categoryAgg",a->a.terms(f->f.field("category3Id"))
                                    .aggregations("topSixAgg",a1->a1.topHits(t1->t1.size(6).sort(st->st.field(fd->fd.field("hotScore").order(SortOrder.Desc)))))
                            )
                    ,
                    AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  从聚合中获取数据
        List<LongTermsBucket> bucketList = searchResponse.aggregations().get("categoryAgg").lterms().buckets().array();
        //  判断集合是否为空
        if (!CollectionUtils.isEmpty(bucketList)){
            //  声明一个map 集合
            List<Map<String, Object>> hashMapList = bucketList.stream().map(termsBucket -> {
                //  创建一个mpa 集合
                HashMap<String, Object> hashMap = new HashMap<>();
                //  获取key，key就是三级分类Id
                long category3Id = termsBucket.key();
                //  获取三级分类的结合列表;
                List<AlbumInfoIndex> albumInfoIndexList = termsBucket.aggregations().get("topSixAgg").topHits().hits().hits().stream().map(hit -> {
                    //  获取数据
                    String jsonData = hit.source().toString();
                    //  数据类型专辑
                    AlbumInfoIndex albumInfoIndex = JSONObject.parseObject(jsonData, AlbumInfoIndex.class);
                    return albumInfoIndex;
                }).collect(Collectors.toList());
                //  通过三级分类I点获取到三级分类对象
                hashMap.put("baseCategory3", category3Map.get(category3Id));
                hashMap.put("list", albumInfoIndexList);
                return hashMap;
            }).collect(Collectors.toList());
            //  返回数据
            return hashMapList;
            //  循环遍历几次
            //  for (LongTermsBucket termsBucket : bucketList) {
            //      //  创建一个mpa 集合
            //      HashMap<String, Object> hashMap = new HashMap<>();
            //      //  获取key，key就是三级分类Id
            //      long category3Id = termsBucket.key();
            //      //  获取三级分类的结合列表;
            //      List<AlbumInfoIndex> albumInfoIndexList = termsBucket.aggregations().get("topSixAgg").topHits().hits().hits().stream().map(hit -> {
            //          //  获取数据
            //          String jsonData = hit.source().toString();
            //          //  数据类型专辑
            //          AlbumInfoIndex albumInfoIndex = JSONObject.parseObject(jsonData, AlbumInfoIndex.class);
            //          return albumInfoIndex;
            //      }).collect(Collectors.toList());
            //      //  通过三级分类I点获取到三级分类对象
            //      hashMap.put("baseCategory3",category3Map.get(category3Id));
            //      hashMap.put("list",albumInfoIndexList);
            //      //  添加map 到集合中
            //      list.add(hashMap);
            //  }
        }
        //  返回 list 集合
        return new ArrayList<>();
    }

    @Override
    public List<String> completeSuggest(String keyword) {
        //  创建一个集合列表
        List<String> list = new ArrayList<>();
        //  先生成dsl语句;
        SearchResponse<SuggestIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(
                    s -> s.index("suggestinfo")
                            .suggest(sg -> sg.suggesters("keyword-suggest", s1 -> s1.prefix(keyword)
                                            .completion(c -> c.field("keyword")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                                    .suggesters("keywordPinyin-suggest", s1 -> s1.prefix(keyword)
                                            .completion(c -> c.field("keywordPinyin")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                                    .suggesters("keywordSequence-suggest", s1 -> s1.prefix(keyword)
                                            .completion(c -> c.field("keywordSequence")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                            )
                    ,
                    SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        //  抽取出一个方法：searchResponse，keywrodType;
        list.addAll(this.getSuggestResult(searchResponse, "keyword-suggest"));
        list.addAll(this.getSuggestResult(searchResponse, "keywordPinyin-suggest"));
        list.addAll(this.getSuggestResult(searchResponse, "keywordSequence-suggest"));
        //  提词的时候，如果数据条数不满足10条,可以采用查询的方式获取数据,
        //        GET /suggestinfo/_search
        //        {
        //            "query": {
        //            "match": {
        //                "title": "三国"
        //            }
        //          }
        //        }
        //  如果不够则补充！
        if (list.size() < 10) {
            //  利用查询方式可以补充！
            SearchResponse<SuggestIndex> response = null;
            try {
                response = this.elasticsearchClient.search(s -> s.index("suggestinfo").query(q -> q.match(m -> m.field("title").query(keyword))), SuggestIndex.class);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            for (Hit<SuggestIndex> hit : response.hits().hits()) {
                //  获取专辑标题
                String title = hit.source().getTitle();
                //  添加到集合中
                list.add(title);
                if (list.size() >= 10) {
                    return list;
                }
            }
        }


        //  返回数据
        return list;
    }

    /**
     * 从提出库中获取数据
     *
     * @param searchResponse
     * @param type
     * @return
     */
    private Collection<String> getSuggestResult(SearchResponse<SuggestIndex> searchResponse, String type) {
        //  获取type 对应的集合数据
        List<Suggestion<SuggestIndex>> suggestionList = searchResponse.suggest().get(type);
        //  判断
        if (!CollectionUtils.isEmpty(suggestionList)) {
            for (Suggestion<SuggestIndex> suggestIndexSuggestion : suggestionList) {
                //  获取options对象
                List<String> list = suggestIndexSuggestion.completion().options().stream().map(option -> {
                    //  获取suggestIndex对象数据
                    SuggestIndex suggestIndex = option.source();
                    //  获取标题
                    return suggestIndex.getTitle();
                }).collect(Collectors.toList());
                //  返回数据
                return list;
            }
        }
        //  默认返回
        return new ArrayList<>();
    }

    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {
        //  1.  先根据用户输入的检索条件，动态生成dsl语句！
        SearchRequest searchRequest = this.queryBuilderDsl(albumIndexQuery);
        //  2.  调用客户端执行查询!
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  3.  获取到结果集！赋值给AlbumSearchResponseVo 对象
        //  创建对象 AlbumSearchResponseVo 在parseResultData 方法中只需要赋值 list 属性！
        AlbumSearchResponseVo albumSearchResponseVo = this.parseResultData(searchResponse);
        //  给对象赋值：
        //        private List<AlbumInfoIndexVo> list = new ArrayList<>();
        //        private Long total;//总记录数
        //        private Integer pageSize;//每页显示的内容
        //        private Integer pageNo;//当前页面
        //        private Long totalPages;
        albumSearchResponseVo.setTotal(searchResponse.hits().total().value());
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        //  总页数： 10 3 4 | 9 3 3
        //  已知总条数，每页显示的条数，求总页数
        Long total = searchResponse.hits().total().value();
        Integer pageSize = albumIndexQuery.getPageSize();
        Long totalPages = total % pageSize == 0 ? total / pageSize : total / pageSize + 1;
        //  Long i = (total + pageSize - 1) / pageSize;
        albumSearchResponseVo.setTotalPages(totalPages);
        //  返回对象
        return albumSearchResponseVo;
    }

    /**
     * 解析结果集
     *
     * @param searchResponse
     * @return
     */
    private AlbumSearchResponseVo parseResultData(SearchResponse<AlbumInfoIndex> searchResponse) {
        //  创建对象
        AlbumSearchResponseVo searchResponseVo = new AlbumSearchResponseVo();
        //  主要给private List<AlbumInfoIndexVo> list = new ArrayList<>(); 赋值
        List<AlbumInfoIndexVo> albumInfoIndexVoList = searchResponse.hits().hits().stream().map(hit -> {
            //  获取里面的数据
            AlbumInfoIndex albumInfoIndex = hit.source();
            //  创建 AlbumInfoIndexVo 对象
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            //  赋值：
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
            //  判断用户是否根据关键词检索，如果根据关键词检索则标题必须是高亮字段！
            if (null != hit.highlight().get("albumTitle")) {
                //  获取高亮专辑标题
                String albumTitle = hit.highlight().get("albumTitle").get(0);
                albumInfoIndexVo.setAlbumTitle(albumTitle);
            }
            //  返回对象
            return albumInfoIndexVo;
        }).collect(Collectors.toList());

        //  赋值
        searchResponseVo.setList(albumInfoIndexVoList);
        //  返回对象
        return searchResponseVo;
    }

    /**
     * 动态生成dsl语句
     *
     * @param albumIndexQuery
     * @return
     */
    private SearchRequest queryBuilderDsl(AlbumIndexQuery albumIndexQuery) {
        //  创建查询对象
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        //  设置索引库
        searchRequestBuilder.index("albuminfo");
        //  创建Query 对象
        Query.Builder queryBuilder = new Query.Builder();
        //  创建BoolQuery对象
        BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();
        //  判断当前是否根据关键词检索
        if (!StringUtils.isEmpty(albumIndexQuery.getKeyword())) {
            boolQueryBuilder.should(s -> s.match(m -> m.field("albumTitle").query(albumIndexQuery.getKeyword())))
                    .should(s -> s.match(m -> m.field("albumIntro").query(albumIndexQuery.getKeyword())));

            //  高亮：
            searchRequestBuilder.highlight(h -> h.fields("albumTitle", hf -> hf.preTags("<span style=color:#f86442>").postTags("</span>")));
        }
        //  判断是否根据分类Id 检索
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory1Id())) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())));
        }
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory2Id())) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())));
        }
        if (!StringUtils.isEmpty(albumIndexQuery.getCategory3Id())) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }
        //  根据属性与属性值进行过滤
        List<String> attributeList = albumIndexQuery.getAttributeList();
        if (!CollectionUtils.isEmpty(attributeList)) {
            for (String attribute : attributeList) {
                //  attribute: 属性id:属性值id
                String[] split = attribute.split(":");
                //  判断是否是为空
                if (null != split && split.length == 2) {
                    boolQueryBuilder.filter(f -> f.nested(n -> n.path("attributeValueIndexList").query(
                            q -> q.bool(b -> b.filter(fl -> fl.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0])))
                                    .filter(fl -> fl.term(t -> t.field("attributeValueIndexList.valueId").value(split[1])))
                            )
                    )));
                }
            }
        }
        //  query:{bool}
        queryBuilder.bool(boolQueryBuilder.build());
        //  query:{}
        searchRequestBuilder.query(queryBuilder.build());
        //  分页：
        searchRequestBuilder.from((albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize());
        searchRequestBuilder.size(albumIndexQuery.getPageSize());

        //  排序：
        //  先获取排序规则 综合排序[1:desc] 播放量[2:desc] 发布时间[3:desc]；asc:升序 desc:降序
        String order = albumIndexQuery.getOrder();
        //  判断是否为空
        if (!StringUtils.isEmpty(order)) {
            //  分割字符串
            String[] split = order.split(":");
            //  判断
            if (null != split && split.length == 2) {
                //  声明一个排序字段
                String field = "";
                switch (split[0]) {
                    case "1":
                        field = "hotScore";
                        break;
                    case "2":
                        field = "playStatNum";
                        break;
                    case "3":
                        field = "createTime";
                        break;
                }
                String finalField = field;
                //  设置排序字段与排序规则
                searchRequestBuilder.sort(s -> s.field(f -> f.field(finalField).order("asc".equals(split[1]) ? SortOrder.Asc : SortOrder.Desc)));
            }
        }
        //   返回 SearchRequest 对象 承载了 dsl 语句
        SearchRequest searchRequest = searchRequestBuilder.build();
        //  直接打印输出
        log.info("dsl语句：" + searchRequest);
        System.out.println(searchRequest.toString());
        //  返回
        return searchRequest;
    }

    @Override
    public void lowerAlbum(Long albumId) {
        //  调用方法
        albumIndexRepository.deleteById(albumId);
        //  删除.
        //  this.redisTemplate.opsForValue().setBit("",albumId,false);
    }
}
